﻿using CPPEI.ETL.DataServiceInterface;
using CPPEI.WebApi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ENT = CPPEI.ETL.Domain.Entities;
using MOD = CPPEI.ETL.Domain.Models;
using SER = CPPEI.ETL.Domain.Services;

namespace CPPEI.ETL.WebApi
{
    [CPPEI.WebApi.PostAction("ETL", "InvokeTask", "1.0")]
    public class InvokeTaskAction : BaseAction<InvokeTaskParams, InvokeTaskResult>
    {
        protected override ActionResult<InvokeTaskResult> OnExecute(ActionContext context, 
            SysParameters sysParameters,
            InvokeTaskParams opParams)
        {
            //opParams.TaskId = new Guid("884fc9ab-5387-4440-8b4f-7fe4ea72ffcd");
            //opParams.ServiceId = new Guid("bf9af2ca-236a-4d91-8cf2-626a076b5afc");
            //opParams.SourceId = new Guid("50a7d7b2-4fa3-4424-94fe-ed9d6b08d64d");

            if(opParams.TaskId == Guid.Empty)
            {
                return new ActionResult<InvokeTaskResult>(false, 0, string.Empty, null);
            }

            if (opParams.Key != CPPEI.ETL.Domain.Cache.TaskAgentKey)
            {
                Logger.WarningToTag(Library.LogTAG, string.Format("InvokeTaskAction.OnExcute,TaskId:{0},DataSourceId:{1},DataServiceId:{2},Key:{3},Invalid Key", opParams.TaskId, opParams.SourceId, opParams.ServiceId, opParams.Key));
                return new ActionResult<InvokeTaskResult>(false, 2, "Invalid key", null);
            }
            Logger.InfoToTag(Library.LogTAG, string.Format("InvokeTaskAction.OnExcute,TaskId:{0},DataSourceId:{1},DataServiceId:{2},Key:{3}", opParams.TaskId, opParams.SourceId, opParams.ServiceId, opParams.Key));

            TaskPool.Start(context.UserId, opParams.TaskId);

            return new ActionResult<InvokeTaskResult>(new InvokeTaskResult());
        }
    }

    public class InvokeTaskParams
    {
        [Parameter]
        public Guid Key { get; set; }

        [Parameter]
        public Guid ServiceId { get; set; }

        [Parameter]
        public Guid SourceId { get; set; }

        [Parameter]
        public Guid TaskId { get; set; }
    }

    public class InvokeTaskResult
    {
    }

    public class TaskPool
    {
        public class TaskInfo
        {
            public string UserId;
            public Guid TaskId;
        }

        private static TaskPool s_pool = new TaskPool();

        private static List<TaskInfo> s_taskInfo = new List<TaskInfo>();
        private static object s_lockObj = new object();

        private static Thread s_thread = null;

        public static void StartImmediately(string userId, Guid taskId)
        {
        }

        public static void Start(string userId, Guid taskId)
        {
            lock (s_lockObj)
            {
                s_taskInfo.Add(new TaskInfo() { UserId = userId, TaskId = taskId });

                if (s_thread == null)
                {
                    s_thread = new Thread(Running);
                    s_thread.Start();
                }
            }
        }

        private static void Running()
        {
            bool isRunning = true;
            while (isRunning)
            {
                // 取出第一个拿来运行
                TaskInfo task = s_taskInfo[0];
                ActualRun(task.UserId, task.TaskId);
                lock (s_lockObj)
                {
                    s_taskInfo.RemoveAt(0);
                    if (s_taskInfo.Count == 0)
                    {
                        s_thread = null;
                        isRunning = false;
                    }
                }
            }
        }

        private static void ActualRun(string userId, Guid taskId)
        {
            try
            {
                SER.TaskService service = new SER.TaskService();
                ServiceResult result = service.RunById(userId, taskId);
                if (result.IsSuccess)
                {
                    Logger.InfoToTag(Library.LogTAG, string.Format("InvokeTaskAction.OnExcute,TaskId:{0},成功", taskId));
                }
                else
                {
                    Logger.InfoToTag(Library.LogTAG, string.Format("InvokeTaskAction.OnExcute,TaskId:{0},失败", taskId));
                }
            }
            catch (Exception ex)
            {
                Logger.ErrorToTag(Library.LogTAG, string.Format("InvokeTaskAction.OnExcute,TaskId:{0},ex:{1}", taskId, ex));
            }
        }
    }
}
